<?
/*
	Класс для связывания различных ресурсов БД. Сейчас модно говорить "Таксономия", по русски - группировка.
	Класс оперирует таблицей (pname, pid, cname, cid).
	
	Создан: 2011-02-18
	Автор: djerom
	Версия: 0.0.0.2
	
	Требует: mvc, dbapi 
*/

	row['id'] = 20;
	row['actors'] = array(
		array (
			'name' => 'ivan',
			'proposal' => 1,
			'adress' => 'semen street 22'
			'films' => array(
				array(
					'id' => 10,
					'name' => 'Hulk'
				),
				array(
					'id' => 6,
					'name' => 'Terminator'
				)
			)
		)
	)
	
	film, actor, oscar
	m		m		m
	
	film{}->actor{}->oscar{}
	
	GET film.name WHERE oscar.name='best actor'
	SELECT film.name FROM film
	JOIN LEFT film_actor ON film_actor.film_id=film.id
	JOIN LEFT actor ON film_actor.actor_id=actor.id
	JOIN LEFT actor_oscar ON actor_oscar.actor_id=actor.id
	JOIN LEFT oscar ON actor_oscar.oscar_id=oscar.id
	, oscar
	
	

	class CTaxonomy
	{
		
			
		var $config = array(
			'links' => 'links', // Таблица связей.
			'ptable' => '',	// Родительская таблица.
			'ctable' => '', // Дочерняя таблица.
			'pname' => 'pname', // Поле ltable с именем родительской таблицы.
			'pid' => 'pid', // Поле ltable с id записи родительской таблицы.
			'cname' => 'cname', // Поле ltable с именем дочерней таблицы.
			'cid' => 'cid');	// Поле ltable с id записи дочерней таблицы.

		function CTaxonomy()
		{
		}
	
		// Присоеденить узел с id=$cid таблицы $cname, к узлу id=$pid таблицы $pname.
		// $check - проверять есть ли связь (дополнительным запросом).
		function attach($cid, $pid, $check = true)
		{
			if ($check && $this->attached($cid, $pid)) return;
		
			echo 'i will attach';
			global $mvc;
			
			$sql = 'INSERT INTO '.$this->config['links'].'(';
			$sql1 = ' VALUES(';
			if ($this->config['fpname'])
			{
				$sql .= $this->config['fpname'].',';
				$sql1 .= "'".$mvc->parse($this->config['ptable'], $this->config)."',";
			}
			
			$sql .= $this->config['fpid'].',';
			$sql1 .= $pid.',';
			
			if ($this->config['fcname'])
			{
				$sql .= $this->config['fcname'].',';
				$sql1 .= "'".$mvc->parse($this->config['ctable'], $this->config)."',";
			}
			
			$sql .= $this->config['fcid'].')';
			$sql1 .= $cid.')';
			
			$sql = $mvc->parse($sql.$sql1);
			
			//echo $sql;
			//die;
			$mvc->db->query($sql, false);
		}
		
		function detach($cid, $pid)
		{
			global $mvc;
			$pid = $pid ? '{pid}='.$pid : 1;
			$cid = $cid ? '{cid}='.$cid : 1;
			if ( ($pid != 1) || ($cid != 1) ) $where = ' WHERE '.$pid.' AND '.$cid;
			else $where = '';
			
			$query = 'DELETE FROM {reallinks} '.$where;//WHERE {pid}='.$pid.' AND {cid}='.$cid;
			$query = $this->make_sql($query);
			$data = $mvc->db->query($query, false);
		}
		
		function make_sql($query)
		{
			global $mvc;
			// Общие
			// {pid} => {links}.{fpid}
			// {cid} => {links}.{fcid}
			// {pname} => {links}.{fpname}
			// {cname} => {links}.{fcname}

			// {from} => {ptable}, {ctable}, {links}
			// {linkid} => {pid}={ptable}.id AND {cid}={ctable}.id
			// {linkname} => {pname}='{ptable}' AND {cname}='{ctable}'
			// {where} => {linkid} [ AND {linkname} ]
			$vars = $this->config;
			$vars['realptable'] = $vars['ptable'];
			$vars['realctable'] = $vars['ctable'];
			$vars['reallinks'] = $vars['links'];
			$vars['ptable'] = '_ptable';
			$vars['ctable'] = '_ctable';
			$vars['links'] = $vars['reallinks'];//'_links';
			$vars['pid'] = '{links}.{fpid}';
			$vars['cid'] = '{links}.{fcid}';
			$vars['pname'] = '{links}.{fpname}';
			$vars['cname'] = '{links}.{fcname}';
			
			$vars['from'] = '{realptable} {ptable}, {realctable} {ctable}, {reallinks} {links}';
			$vars['linkid'] = '{pid}={ptable}.id AND {cid}={ctable}.id';
			$vars['linkname'] = ($vars['fpname'] && $vars['fcname']) ? '{pname}=\'{realptable}\' AND {cname}=\'{realctable}\'' : '1';
			$vars['where'] = '{linkid} AND {linkname}';
			
			return $mvc->parse($query, $vars, true);
		}
		
		// Прикреплен ли узел $cid к узлу $pid.
		function attached($cid, $pid)
		{
			global $mvc;
		
			$query = $this->make_sql('SELECT count(*) as cnt FROM {reallinks} WHERE {linkname} 
				AND {cid}='.$cid.' AND {pid}='.$pid);
			
			$data = $mvc->db->get_data($query);
			return $data[0]['cnt'];







		
			$query = 'SELECT count(*) as cnt FROM {links} _links WHERE {linkage}';
		
			// Формируем FROM из трех таблиц, дети - родители - связи. 
			$from = '{links} _links, {ptable} _ptable, {ctable} _ctable';

			// Формируем условие связи.
			$ptable = $this->config['ptable'];
			$ctable = $this->config['ctable'];
			$fpname = $this->config['pname'];
			$fcname = $this->config['cname'];
			$fpid = $this->config['pid'];
			$fcid = $this->config['cid'];
			$linkage = "";
			
			$linkage = "_links.$fpid=$pid AND _links.$fcid=$cid";
			if ($fpname && $fcname)
				$linkage .= " AND _links.$fpname='$ptable' AND _links.$fcname='$ctable'";

			// Заменяем {from} на $from связей.
			$query = str_replace('{from}', $from, $query);

			// Заменяем {linkage} на $from связей.
			$query = str_replace('{linkage}', $linkage, $query);

			// Заменяем {links} на таблицу связей.
			$query = str_replace('{links}', $this->config['table'], $query);

			// Заменяем {from} на $from связей.
			$query = str_replace('{ptable}', $this->config['ptable'], $query);

			// Заменяем {from} на $from связей.
			$query = str_replace('{ctable}', $this->config['ctable'], $query);

			$query = $mvc->parse($query);

			$data = $mvc->db->get_data($query);
			return $data[0]['cnt'];
		}
		
		// Получить данные по запросу. Запрос подготавливается.
		function get_data($query)
		{
			global $mvc;
		
			$query = $this->make_sql($query);
			return $mvc->db->get_data($query);
		
		
		
		
		
		
			// Формируем FROM из трех таблиц, дети - родители - связи. 
			$from = '{links} _links, {ptable} _ptable, {ctable} _ctable';

			// Формируем условие связи.
			$ptable = $this->config['ptable'];
			$ctable = $this->config['ctable'];
			$pname = $this->config['pname'];
			$cname = $this->config['cname'];
			$pid = $this->config['pid'];
			$cid = $this->config['cid'];
			$linkage = "";
			
			$linkage = "_ptable.id=_links.$pid AND _ctable.id=_links.$cid";
			if ($pname && $cname)
				$linkage .= " AND _links.$pname='$ptable' AND _links.$cname='$ctable'";

			// Заменяем {from} на $from связей.
			$query = str_replace('{from}', $from, $query);

			$query = str_replace('{pid}', "_links.$pid", $query);

			$query = str_replace('{cid}', "_links.$cid", $query);

			// Заменяем {linkage} на $from связей.
			$query = str_replace('{linkage}', $linkage, $query);

			// Заменяем {links} на таблицу связей.
			$query = str_replace('{links}', $this->config['table'], $query);

			// Заменяем {from} на $from связей.
			$query = str_replace('{ptable}', $this->config['ptable'], $query);

			// Заменяем {from} на $from связей.
			$query = str_replace('{ctable}', $this->config['ctable'], $query);

			$query = $mvc->parse($query);

			//return $mvc->db->get_data($query);
			return $query;
		}
	}
?>
